﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YXH_Tools_Files.Tools_CSV;
using YXH_Tools_Files.Tools_DirectoryandFile;
using YXH_Tools_Files.Tools_List;

namespace YXH_Tools_Files.Tools_EdgeComputing
{
    /// <summary>
    ///  FileInfo文件合并操作类，包括合并后文件名，合并规则等
    /// </summary>
    public static class FileInfoOperation_Combination
    {
        /// <summary>
        /// （专用于边缘采集器）生成合并好的csv文件名（每30分钟模式）
        /// </summary>
        /// <param name="file">FileInfo类型文件</param>
        /// <returns>string合并后文件名</returns>
        public static string YXHGetCombinedFilename(this FileInfo file)
        {
            string date = file.Name.Split("-")[0];
            string hour = file.Name.Split("-")[1].Split("_")[0];
            string minute = file.Name.Split("-")[1].Split("_")[1];
            if (Convert.ToInt16(minute) < 30)
            {
                return date + "-" + hour + "_" + "01" + "_00-F_1.csv";
            }
            else
            {
                return date + "-" + hour + "_" + "31" + "_00-F_1.csv";
            }
        }
        /// <summary>
        ///（专用于边缘采集器） 返回一组以30分钟来分割的时间线，如（2022-07-11 00:00:00），一共有24个
        /// </summary>
        /// <param name="file">FileInfo类型文件</param>
        /// <returns>List<DateTime></returns>
        public static List<DateTime> YXHGetSplitTime(this FileInfo file)
        {
            List<DateTime> list = new List<DateTime>();
            string date = file.YXHFilenametoDate();
            for (int i = 0; i < 24; i++)
            {
                list.Add(Convert.ToDateTime(date + " " + i.ToString("D2") + ":00:00"));
                list.Add(Convert.ToDateTime(date + " " + i.ToString("D2") + ":30:00"));
            }
            list.Add(Convert.ToDateTime(date + " " + "23:59:59"));
            return list;
        }
        /// <summary>
        /// (弃用）（专用于边缘采集器）按照时间顺序来分类并返回分类好的CSV文件组
        /// </summary>
        /// <param name="files">FileInfo类型文件组</param>
        /// <returns>List<List<FileInfo>></returns>
        public static List<List<FileInfo>> YXHClassifyFilebyTime(this FileInfo[] files)
        {
            //创建一个totallist，用于存储每半个小时的list
            List<List<FileInfo>> totallist = new List<List<FileInfo>>();
            //创建48个List<FileInfo>()，并添加到totallist
            for (int i = 0; i < 49; i++)
            {
                totallist.Add(new List<FileInfo>());
            }
            if (files.Length > 0)
            {
                //用第一个文件来获取48个分割时间线，因为要用到第一个文件的文件名
                List<DateTime> timelist = files[0].YXHGetSplitTime();
                foreach (var file in files)
                {
                    for (int i = 0; i < timelist.Count; i++)
                    {
                        if (file.YXHFilenametoDateTime() >= timelist[i] && file.YXHFilenametoDateTime() < timelist[i + 1])
                        {
                            totallist[i].Add(file);
                        }
                    }
                }
            }
            return totallist;
        }

        /// <summary>
        /// （专用于边缘采集器）按照时间顺序来分类并返回分类好的CSV文件组V2版本，统一为MileageClassifyClass类，有起始终止index等信息
        /// </summary>
        /// <param name="files">FileInfo类型文件组</param>
        /// <returns>List<MileageClassifyClass></returns>
        public static List<MileageClassifyClass> YXHClassifyFilebyTimeV2(this FileInfo[] files)
        {
            //创建一个totallist，用于存储每半个小时的list
            List<MileageClassifyClass> totallist = new List<MileageClassifyClass>();
            //创建48个List<FileInfo>()，并添加到totallist
            for (int i = 0; i < 49; i++)
            {
                totallist.Add(new MileageClassifyClass());
            }
            if (files.Length > 0)
            {
                //用第一个文件来获取48个分割时间线，因为要用到第一个文件的文件名
                List<DateTime> timelist = files[0].YXHGetSplitTime();
                foreach (var file in files)
                {
                    for (int i = 0; i < timelist.Count; i++)
                    {
                        if (file.YXHFilenametoDateTime() >= timelist[i] && file.YXHFilenametoDateTime() < timelist[i + 1])
                        {
                            totallist[i].filelist?.Add(file);
                            totallist[i].endrowindex = 0;
                            totallist[i].startrowindex = 0;
                            totallist[i].endfileindex = 0;
                            totallist[i].startfileindex = 0;
                            totallist[i].endfileextramileage = 0;
                        }
                    }
                }
            }
            return totallist;
        }


        /// <summary>
        /// (弃用）（专用于边缘采集器）按照基准里程来分类并返回分类好的CSV文件组
        /// </summary>
        /// <param name="files">文件列表</param>
        /// <param name="permileage">里程分割标准值</param>
        /// <param name="spdindex">速度通道在csv文件里的index</param>
        /// <returns></returns>
        public static List<List<FileInfo>>  YXHClassifyFilebyMileage(this FileInfo[] files,int permileage,int spdindex)
        {
            
            //创建存储每个文件的里程数的list
            List<double> mileages=new List<double>();
            foreach (var file in files)
            {
                //获得速度list
               var spdlist= CSVOperator.YXHReadOneCollumnfromCSV2List(file.FullName, spdindex);
                //获得timelist
                var timelist = CSVOperator.YXHReadOneCollumnfromCSV2List(file.FullName, 0);
                if (spdlist != null && timelist != null)
                {
                    mileages.Add(Mileage.ReturnSumDistanceperFile(spdlist, timelist));//把每个文件的里程数添加到这个mileageslist里面
                }
            }
            //获得按照基准里程分好的每一段的起始文件index和终止文件index
            var indexlist=Mileage.GetIndexRanges(mileages, permileage);
            //创建一个totallist，用于存储每permileage公里数的文件list
            List<List<FileInfo>> totallist = new List<List<FileInfo>>();
            //有几个indexlist类就添加几个到totallist
            for (int i = 0; i < indexlist.Count; i++)
            {
                totallist.Add(new List<FileInfo>());
            }
            for (int j = 0; j < indexlist.Count; j++)
            {
                for (int i = 0; i < files.Length; i++)
                {
                    if (i >= indexlist[j][0]&& i <= indexlist[j][1])//利用index里的边界来划分files
                    totallist[j].Add(files[i]);
                }
            }
            return totallist;
        }

        /// <summary>
        /// （专用于边缘采集器）按照基准里程来分类并返回分类好的MileageClassifyClass,统一为MileageClassifyClass类，有起始终止index等信息
        /// </summary>
        /// <param name="files"></param>
        /// <param name="permileage"></param>
        /// <param name="spdindex"></param>
        /// <returns></returns>
        public static List<MileageClassifyClass> YXHClassifyFilebyMileagePrecise(this FileInfo[] files, int permileage, int spdindex)
        {
            //创建存储每个文件的里程数的list
            List<double> cummileages = new List<double>();
            foreach (var file in files)
            {
                //获得速度list
                var spdlist = CSVOperator.YXHReadOneCollumnfromCSV2List(file.FullName, spdindex);
                //获得timelist
                var timelist = CSVOperator.YXHReadOneCollumnfromCSV2List(file.FullName, 0);
                if (spdlist != null && timelist != null)
                {
                    cummileages.Add(Mileage.ReturnSumDistanceperFile(spdlist, timelist));//把每个文件的里程数添加到这个mileageslist里面
                }
            }
            List<MileageClassifyClass> result = new List<MileageClassifyClass>();
            var startfileindex = 0;
            var sum = 0.0;
            for (var i = 0; i < cummileages.Count; i++)
            {
                sum += cummileages[i];
                //先判断是否超过标准里程-5的差值，超过了才能进行下面的分割判断，没超过继续叠加
                if (sum >= permileage - 5)
                {
                    //如果叠加里程达到标准单位里程的差值5米以内则不会分割单个文件
                    if (Math.Abs(sum - permileage) <= 5)
                    {
                        //先判断result里面有没有数据，没有数据说明是第一次叠加里程，不用考虑起始文件的行数
                        if (result.Count == 0)
                        {
                            //倒数第二第三个数字表示起始文件的行数和终止文件的行数，都等于0表示包含所有行，不会分割单个文件，最后一个数表示终止文件分割的里程
                            //result.Add(new List<int> { startfileindex, i, 0, 0, 0 });
                            //result.Add(new MileageClassifyClass());
                            MileageClassifyClass mlist = new MileageClassifyClass();
                            mlist.endrowindex = 0;
                            mlist.startrowindex = 0;
                            mlist.endfileindex = i;
                            mlist.startfileindex = startfileindex;
                            mlist.endfileextramileage = 0;
                            
                            for (int j = mlist.startfileindex; j <= mlist.endfileindex; j++)
                            {
                                mlist.filelist?.Add(files[j]);
                            }
                            result.Add(mlist);
                            //startfileindex = i + 1;//这里由于终止判断了不会分割，所以下一次的起始文件index加1
                            //sum = 0;
                        }
                        //要考虑上一次是否有分割过
                        else
                        {
                            //如果前一个数据的终止文件行数有值，说明前面一个数据有分割过，那这一次的起始文件还是原来上一次的终止文件
                            if (result[result.Count - 1].endrowindex > 0)
                            {
                                MileageClassifyClass mlist = new MileageClassifyClass();
                                mlist.endrowindex = 0;
                                mlist.startrowindex = result[result.Count - 1].endrowindex;
                                mlist.endfileindex = i;
                                mlist.startfileindex = result[result.Count - 1].endfileindex;
                                mlist.endfileextramileage = 0;
                                for (int j = mlist.startfileindex; j <= mlist.endfileindex; j++)
                                {
                                    mlist.filelist?.Add(files[j]);
                                }
                                result.Add(mlist);
                            }
                            //说明前一个数据的终止文件行数为0，没有分割过，那这一次的起始文件就是startfileindex
                            else
                            {
                                MileageClassifyClass mlist = new MileageClassifyClass();
                                mlist.endrowindex = 0;
                                mlist.startrowindex = 0;
                                mlist.endfileindex = i;
                                mlist.startfileindex = startfileindex;
                                mlist.endfileextramileage = 0;
                                for (int j = mlist.startfileindex; j <= mlist.endfileindex; j++)
                                {
                                    mlist.filelist?.Add(files[j]);
                                }
                                result.Add(mlist);
                            }

                        }
                        startfileindex = i + 1;//这里由于终止文件判断了不会分割，所以下一次的起始文件index加1
                        sum = 0;
                    }
                    //差值超过5就会分割文件
                    else
                    {

                        //获得准确差值
                        var diff = sum - permileage;
                        //获得要分割文件的速度cummileages
                        var spdcummileages = CSVOperator.YXHReadOneCollumnfromCSV2List(files[i].FullName, spdindex);
                        //获得要分割文件的timecummileages
                        var timecummileages = CSVOperator.YXHReadOneCollumnfromCSV2List(files[i].FullName, 0);
                        if (spdcummileages != null && timecummileages != null)
                        {
                            var mileage = Mileage.ReturnSingleDistanceperFile(spdcummileages, timecummileages);//计算这个文件的每行里程数
                            var singlesum = 0.0;
                            //倒序循环叠加每行里程，如超过差值停止循环，找到此文件要分割的行数
#pragma warning disable CS0162 // 检测到无法访问的代码
                            for (int j = mileage.Count - 1; j >= 0; j--)
                            {
                                singlesum += mileage[j];
                                if (singlesum >= diff)
                                {
                                    if (result.Count == 0)
                                    {
                                        MileageClassifyClass mlist = new MileageClassifyClass();
                                        mlist.endrowindex = j;
                                        mlist.startrowindex = 0;
                                        mlist.endfileindex = i;
                                        mlist.startfileindex = startfileindex;
                                        mlist.endfileextramileage = diff;
                                        for (int k = mlist.startfileindex; k <= mlist.endfileindex; k++)
                                        {
                                            mlist.filelist?.Add(files[k]);
                                        }
                                        result.Add(mlist);
                                        //result.Add(new List<int> { startfileindex, i, 0, j, Convert.ToInt32(diff) });

                                    }
                                    //说明result之前有值
                                    else
                                    {
                                        //如果前一个数据的终止文件行数有值，说明前面一个数据有分割过，那这一次的起始文件还是原来上一次的终止文件
                                        if (result[result.Count - 1].endrowindex > 0)
                                        {

                                            //这一次的起始文件为上一次的终止文件，终止文件为i，起始行数为前一次的终止文件的行数，终止文件的行数为j，里程差值为diff
                                            MileageClassifyClass mlist = new MileageClassifyClass();
                                            mlist.endrowindex = j;
                                            mlist.startrowindex = result[result.Count - 1].endrowindex;
                                            mlist.endfileindex = i;
                                            mlist.startfileindex = result[result.Count - 1].endfileindex;
                                            mlist.endfileextramileage = diff;
                                            for (int k = mlist.startfileindex; k <= mlist.endfileindex; k++)
                                            {
                                                mlist.filelist?.Add(files[k]);
                                            }
                                            result.Add(mlist);
                                            //result.Add(new List<int> { result[result.Count - 1][1], i, result[result.Count - 1][3], j, Convert.ToInt32(diff) });
                                        }
                                        else
                                        {
                                            MileageClassifyClass mlist = new MileageClassifyClass();
                                            mlist.endrowindex = j;
                                            mlist.startrowindex = 0;
                                            mlist.endfileindex = i;
                                            mlist.startfileindex = startfileindex;
                                            mlist.endfileextramileage = diff;
                                            for (int k = mlist.startfileindex; k <= mlist.endfileindex; k++)
                                            {
                                                mlist.filelist?.Add(files[k]);
                                            }
                                            result.Add(mlist);
                                            //result.Add(new List<int> { startfileindex, i, 0, j, Convert.ToInt32(diff) });
                                        }
                                    
                                    }
                                    startfileindex = i;//由于这一次分割过，所以下一次的起始文件还是i
                                    sum = diff;//由于这一次分割过，所以下一次的sum计数要从diff算起
                                    break;//停止循环
                                }
                                
                            }
#pragma warning restore CS0162 // 检测到无法访问的代码

                        }

                    }
                }

            }
            //文件循环结束后startfileindex没有到最后一个文件时，说明合并完后还有剩余文件加起来没有到标准里程
            if (startfileindex < cummileages.Count)
            {
                //说明所有文件加起来的里程没有超过1km
                if (result.Count == 0)
                {
                    MileageClassifyClass mlist = new MileageClassifyClass();
                    mlist.endrowindex = 0;
                    mlist.startrowindex = 0;
                    mlist.endfileindex = cummileages.Count - 1;
                    mlist.startfileindex = startfileindex;
                    mlist.endfileextramileage = 0;
                    for (int j = mlist.startfileindex; j <= mlist.endfileindex; j++)
                    {
                        mlist.filelist?.Add(files[j]);
                    }
                    result.Add(mlist);
                    //result.Add(new List<int> { startfileindex, cummileages.Count - 1, 0, 0, 0 });
                }
                else
                {
                    //说明前面一组有分割
                    if (result[result.Count - 1].endrowindex > 0)
                    {
                        MileageClassifyClass mlist = new MileageClassifyClass();
                        mlist.endrowindex = 0;
                        mlist.startrowindex = result[result.Count - 1].endrowindex;
                        mlist.endfileindex = cummileages.Count - 1;
                        mlist.startfileindex = result[result.Count - 1].endfileindex;
                        mlist.endfileextramileage = 0;
                        for (int k = mlist.startfileindex; k <= mlist.endfileindex; k++)
                        {
                            mlist.filelist?.Add(files[k]);
                        }
                        result.Add(mlist);
                        //result.Add(new List<int> { result[result.Count - 1][1], cummileages.Count - 1, result[result.Count - 1][3], 0, 0 });

                    }
                    //说明前面一组没有分割
                    else
                    {
                        MileageClassifyClass mlist = new MileageClassifyClass();
                        mlist.endrowindex = 0;
                        mlist.startrowindex = 0;
                        mlist.endfileindex = cummileages.Count - 1;
                        mlist.startfileindex = startfileindex;
                        mlist.endfileextramileage = 0;
                        for (int j = mlist.startfileindex; j <= mlist.endfileindex; j++)
                        {
                            mlist.filelist?.Add(files[j]);
                        }
                        result.Add(mlist);
                        //result.Add(new List<int> { startfileindex, cummileages.Count - 1, 0, 0, 0 });
                    }
                }
            }
            return result;

        }


        /// <summary>
        /// （专用于边缘采集器）查找0kb的数据，并把它替换成txt文件
        /// </summary>
        /// <param name="fileInfos">文件</param>
        public static void YXHTransferZeroCsvtoTxt(this FileInfo[] fileInfos)
        {
            if (fileInfos.Length > 0)
            {
                foreach (var item in fileInfos)
                {
                    if (item.Length == 0)
                    {
                        var txt = item.FullName.Replace("csv", "txt");
                        File.Move(item.FullName, txt);
                    }
                }
            }
        }
        /// <summary>
        /// （专用于边缘采集器）查找csv0kb的数据，并把它删除
        /// </summary>
        /// <param name="fileInfos">文件</param>
        public static void YXHDeleteZeroCsv(this FileInfo[] fileInfos)
        {
            if (fileInfos.Length > 0)
            {
                foreach (var item in fileInfos)
                {
                    if (item.Length == 0)
                    {
                       item.FullName.YXHDeleteFile();
                    }
                }
            }
        }
        /// <summary>
        /// (弃用）（专用于边缘采集器）按照TXT来分类并返回分类好的CSV文件组
        /// </summary>
        /// <param name="allfile">FileInfo类型文件组</param>
        /// <returns></returns>
        public static List<List<FileInfo>> YXHClassifyFilebyTxt(this FileInfo[] allfile)
        {
            //创建一个totallist，用于存储每2个txt中间的数据的list
            List<List<FileInfo>> totallist = new List<List<FileInfo>>();
            List<int> txtindex = new List<int>();
            for (int i = 0; i < allfile.Length; i++)
            {
                if (allfile[i].Extension.ToLower() == ".txt")
                {
                    txtindex.Add(i);
                }
            }
            //txt有1个以上
            if (txtindex.Count > 0)
            {
                //添加第一个list，用于存放第一个txt之前的csv数据，不管有没有csv
                totallist.Add(new List<FileInfo>());
                for (int j = 0; j < txtindex[0]; j++)
                {
                    totallist[0].Add(allfile[j]);
                }
                for (int i = 0; i < txtindex.Count - 1; i++)
                {
                    totallist.Add(new List<FileInfo>());
                    //如果第一个数的后一个数比第二个数前一个数小，就说明中间有csv需要合并
                    if (txtindex[i] + 1 <= txtindex[i + 1] - 1)
                    {
                        for (int j = txtindex[i] + 1; j <= txtindex[i + 1] - 1; j++)
                        {
                            totallist[i+1].Add(allfile[j]);//这里totallist[i+1]是因为totallist[0]已经有了，必须从1开始
                        }
                    }
                }
                //添加最后一个list，用于存放最后一个txt之后的csv数据，不管有没有csv
                totallist.Add(new List<FileInfo>());
                for (int j = txtindex[txtindex.Count - 1] + 1; j < allfile.Length; j++)
                {
                    totallist[totallist.Count - 1].Add(allfile[j]);
                }
            }
            //如果没有txt，那就直接把所有的csv文件放在totallist[0]里进行合并
            else
            {
                totallist.Add(new List<FileInfo>());
                for (int j = 0; j < allfile.Length; j++)
                {
                    totallist[0].Add(allfile[j]);
                }
            }
            return totallist;
        }


        /// <summary>
        ///（专用于边缘采集器）按照TXT来分类并返回分类好的CSV文件组V2版本，统一为MileageClassifyClass类，有起始终止index等信息
        /// </summary>
        /// <param name="allfile">FileInfo类型文件组</param>
        /// <returns></returns>
        public static List<MileageClassifyClass> YXHClassifyFilebyTxtV2(this FileInfo[] allfile)
        {
            //创建一个totallist，用于存储每2个txt中间的数据的list
            List<MileageClassifyClass> totallist = new List<MileageClassifyClass>();
            List<int> txtindex = new List<int>();
            for (int i = 0; i < allfile.Length; i++)
            {
                if (allfile[i].Extension.ToLower() == ".txt")
                {
                    txtindex.Add(i);
                }
            }
            //txt有1个以上
            if (txtindex.Count > 0)
            {
                //添加第一个list，用于存放第一个txt之前的csv数据，不管有没有csv
                totallist.Add(new MileageClassifyClass());
                for (int j = 0; j < txtindex[0]; j++)
                {
                    totallist[0].filelist?.Add(allfile[j]);
                    totallist[0].endrowindex = 0;
                    totallist[0].startrowindex = 0;
                    totallist[0].endfileindex = 0;
                    totallist[0].startfileindex = 0;
                    totallist[0].endfileextramileage = 0;
                }
                for (int i = 0; i < txtindex.Count - 1; i++)
                {
                    totallist.Add(new MileageClassifyClass());
                    //如果第一个数的后一个数比第二个数前一个数小，就说明中间有csv需要合并
                    if (txtindex[i] + 1 <= txtindex[i + 1] - 1)
                    {
                        for (int j = txtindex[i] + 1; j <= txtindex[i + 1] - 1; j++)
                        {
                            totallist[i + 1].filelist?.Add(allfile[j]);//这里totallist[i+1]是因为totallist[0]已经有了，必须从1开始
                            totallist[i+1].endrowindex = 0;
                            totallist[i+1].startrowindex = 0;
                            totallist[i+1].endfileindex = 0;
                            totallist[i+1].startfileindex = 0;
                            totallist[i+1].endfileextramileage = 0;
                        }
                    }
                }
                //添加最后一个list，用于存放最后一个txt之后的csv数据，不管有没有csv
                totallist.Add(new MileageClassifyClass());
                for (int j = txtindex[txtindex.Count - 1] + 1; j < allfile.Length; j++)
                {
                    totallist[totallist.Count - 1].filelist?.Add(allfile[j]);
                    totallist[totallist.Count - 1].endrowindex = 0;
                    totallist[totallist.Count - 1].startrowindex = 0;
                    totallist[totallist.Count - 1].endfileindex = 0;
                    totallist[totallist.Count - 1].startfileindex = 0;
                    totallist[totallist.Count - 1].endfileextramileage = 0;
                }
            }
            //如果没有txt，那就直接把所有的csv文件放在totallist[0]里进行合并
            else
            {
                totallist.Add(new MileageClassifyClass());
                for (int j = 0; j < allfile.Length; j++)
                {
                    totallist[0].filelist?.Add(allfile[j]);
                    totallist[0].endrowindex = 0;
                    totallist[0].startrowindex = 0;
                    totallist[0].endfileindex = 0;
                    totallist[0].startfileindex = 0;
                    totallist[0].endfileextramileage = 0;
                }
            }
            return totallist;
        }


        /// <summary>
        /// （专用于边缘采集器）按照txt来合并csv后的csv文件名，第一个csv和最后一个csv文件名组合而成
        /// </summary>
        /// <param name="file1">List里第一个file</param>
        /// <param name="file2">List里最后一个file</param>
        /// <returns>string合并后的文件名</returns>
        public static string YXHGetCombinedFilenamebyTxt(this FileInfo file1, FileInfo file2)
        {
            var file1name = file1.Name.Split(".")[0];
            var file2name = file2.Name.Split(".")[0];
            return file1name + "-to-" + file2name + ".csv";
        }
        /// <summary>
        /// （专用于边缘采集器）在指定文件夹下创建done.txt文件
        /// </summary>
        /// <param name="directorypath">日期文件夹路径</param>
        public static void YXHAddTxt( string directorypath)
        {
            Directory.CreateDirectory(directorypath);
            var txtname = directorypath.Split('\\');
            string txtpath = Path.Combine(directorypath, txtname[txtname.Length-1]+"_done.txt");
            FileStream fs = new FileStream(txtpath, FileMode.Append);
            StreamWriter? wr = null;
            wr = new StreamWriter(fs);
            wr.Close();
        }
    }
}
